package xyz.xfcloud.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 网络连接客户端工具类
 */
public class HttpClientUtils {
    //最大连接数
    private static int maxTotal = 100;
    //并发数
    private static int defaultMaxPerRoute = 50;
    //创建连接的最长时间
    private static int connectTimeout = 3000;
    //从连接池中获取到连接的最长时间
    private static int connectionRequestTimeout = 3000;
    //数据传输的最长时间
    private static int socketTimeout = 100000;

    private static CloseableHttpClient httpClient;

    static {
        PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
        //最大连接数
        httpClientConnectionManager.setMaxTotal(maxTotal);
        //并发数
        httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout)
                .setExpectContinueEnabled(true).build();
        httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig)
                .setConnectionManager(httpClientConnectionManager).build();
    }

    /**
     * 发送 GET 请求（HTTP），不带输入数据
     *
     * @param url
     * @return
     */
    public static String doGet(String url) throws Exception {
        return doGet(url, new HashMap<String, Object>());
    }

    /**
     * 发送 GET 请求（HTTP），K-V形式
     *
     * @param url
     * @param params
     * @return
     */
    public static String doGet(String url, Map<String, Object> params) throws Exception {
        String apiUrl = url;
        StringBuffer param = new StringBuffer();
        int i = 0;
        for (String key : params.keySet()) {
            if (i == 0) {
                param.append("?");
            } else {
                param.append("&");
            }
            param.append(key).append("=").append(params.get(key));
            i++;
        }
        apiUrl += param;
        String result = null;
        CloseableHttpResponse response = null;
        HttpGet httpGet = new HttpGet(apiUrl);
        response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        result = EntityUtils.toString(entity, "UTF-8");
        response.close();
        return result;
    }


    public static byte[] doGets(String url) throws Exception {
        CloseableHttpResponse response = null;
        HttpGet httpGet = new HttpGet(url);
        response = httpClient.execute(httpGet);
        try (InputStream entity = response.getEntity().getContent()) {
            byte[] buf = new byte[1024];
            int rc = 0;
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            while ((rc = entity.read(buf)) > 0) {
                swapStream.write(buf, 0, rc);
            }
            response.close();
            return swapStream.toByteArray();
        }
    }


    /**
     * 发送 POST 请求（HTTP），不带输入数据
     *
     * @param apiUrl
     * @return
     */
    public static String doPost(String apiUrl) throws Exception {
        return doPost(apiUrl, new HashMap<String, Object>());
    }

    /**
     * 发送 POST 请求（HTTP），K-V形式
     *
     * @param apiUrl API接口URL
     * @param params 参数map
     * @return
     */
    public static String doPost(String apiUrl, Map<String, Object> params) throws Exception {
        return doPost(apiUrl, params, null);
    }

    public static String doPost(String apiUrl, Map<String, Object> params, String contentType) throws Exception {
        return doPost(apiUrl, params, contentType, null);
    }

    public static String doPost(String apiUrl, Map<String, Object> params, String contentType, Map<String, String> headerMap) throws Exception {
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size());
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());
            pairList.add(pair);
        }

        if (headerMap != null && headerMap.size() > 0) {
            for (Map.Entry<String, String> header : headerMap.entrySet()) {
                httpPost.setHeader(header.getKey(), header.getValue());
            }
        }

        if (pairList.size() > 0) {

            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8"));

            if (!StringUtils.isEmpty(contentType)) {
                urlEncodedFormEntity.setContentType(contentType);
            }

            httpPost.setEntity(urlEncodedFormEntity);
        }

        response = httpClient.execute(httpPost);

        HttpEntity entity = response.getEntity();
        httpStr = EntityUtils.toString(entity, "UTF-8");
        response.close();
        return httpStr;
    }


    /**
     * 发送 POST 请求（HTTP），JSON形式
     *
     * @param apiUrl
     * @param json      json对象
     * @param headerMap 请求头
     * @return
     */
    public static String doPost(String apiUrl, String json, Map<String, String> headerMap) throws Exception {
        return doPost(apiUrl, json, headerMap, false);
    }

    /**
     * 发送 JSON POST 请求
     *
     * @param apiUrl                请求URL
     * @param json                  请求数据
     * @param headerMap             自定义Header
     * @param removeContentEncoding 请求去掉ContentEncoding（神策不支持）
     * @return
     * @throws Exception
     */
    public static String doPost(String apiUrl, String json, Map<String, String> headerMap, Boolean removeContentEncoding) throws Exception {
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        if (headerMap != null && headerMap.size() > 0) {
            for (Map.Entry<String, String> header : headerMap.entrySet()) {
                httpPost.setHeader(header.getKey(), header.getValue());
            }
        }
        //解决中文乱码问题
        StringEntity stringEntity = new StringEntity(json, "UTF-8");
        // 神策不支持UTF-8格式的ContentEncoding
        if (!removeContentEncoding) {
            stringEntity.setContentEncoding("UTF-8");
        }
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        httpStr = EntityUtils.toString(entity, "UTF-8");
        response.close();
        return httpStr;
    }
}
